
$RedTurret_AnimThread = 0;

if(!isFunction(Armor             , onAdd      )) eval("function Armor::           ::onAdd      (){}");
if(!isFunction(WheeledVehicleData, onAdd      )) eval("function WheeledVehicleData::onAdd      (){}");
if(!isFunction(FlyingVehicleData , onAdd      )) eval("function FlyingVehicleData ::onAdd      (){}");
if(!isFunction(Armor             , onDamage   )) eval("function Armor             ::onDamage   (){}");
if(!isFunction(WheeledVehicleData, onDamage   )) eval("function WheeledVehicleData::onDamage   (){}");
if(!isFunction(FlyingVehicleData , onDamage   )) eval("function FlyingVehicleData ::onDamage   (){}");
if(!isFunction(Armor             , onRemove   )) eval("function Armor             ::onRemove   (){}");
if(!isFunction(WheeledVehicleData, onRemove   )) eval("function WheeledVehicleData::onRemove   (){}");
if(!isFunction(FlyingVehicleData , onRemove   )) eval("function FlyingVehicleData ::onRemove   (){}");
if(!isFunction(Armor             , onTrigger  )) eval("function Armor             ::onTrigger  (){}");
if(!isFunction(WheeledVehicleData, onTrigger  )) eval("function WheeledVehicleData::onTrigger  (){}");
if(!isFunction(FlyingVehicleData , onTrigger  )) eval("function FlyingVehicleData ::onTrigger  (){}");
if(!isFunction(WheeledVehicleData, onCollision)) eval("function WheeledVehicleData::onCollision(){}");
if(!isFunction(FlyingVehicleData , onCollision)) eval("function FlyingVehicleData ::onCollision(){}");
if(!isFunction(Armor             , onDisabled )) eval("function Armor             ::onDisabled (){}");
if(!isFunction(Armor             , onMount    )) eval("function Armor             ::onMount    (){}");
if(!isFunction(WeaponImage       , onFire     )) eval("function WeaponImage       ::onFire     (){}");
if(!isFunction(Projectile        , onAdd      )) eval("function Projectile        ::onAdd      (){}");

package RedBase_MountedTurret {
	function Armor::onAdd(%data, %obj) {
		parent::onAdd(%data, %obj);
		MountedTurret_VehicleCreated(%obj);
		MountedTurret_ArmorCreated(%obj);
	}
	function WheeledVehicleData::onAdd(%data, %obj) {
		parent::onAdd(%data, %obj);
		MountedTurret_VehicleCreated(%obj);
	}
	function FlyingVehicleData::onAdd(%data, %obj) {
		parent::onAdd(%data, %obj);
		MountedTurret_VehicleCreated(%obj);
	}
	
	function Armor::onDamage(%data, %obj, %damage) {
		parent::onDamage(%data, %obj, %damage);
		MountedTurret_VehicleDamaged(%obj);
	}
	function WheeledVehicleData::onDamage(%data, %obj) {
		parent::onDamage(%data, %obj);
		MountedTurret_VehicleDamaged(%obj);
	}
	function FlyingVehicleData::onDamage(%data, %obj) {
		parent::onDamage(%data, %obj);
		MountedTurret_VehicleDamaged(%obj);
	}
	
	function Armor::onRemove(%data, %obj) {
		parent::onRemove(%data, %obj);
		MountedTurret_VehicleDestroyed(%obj, 1);
	}
	function WheeledVehicleData::onRemove(%data, %obj) {
		parent::onRemove(%data, %obj);
		MountedTurret_VehicleDestroyed(%obj, 1);
	}
	function FlyingVehicleData::onRemove(%data, %obj) {
		parent::onRemove(%data, %obj);
		MountedTurret_VehicleDestroyed(%obj, 1);
	}
	
	function Armor::onTrigger(%data, %obj, %trig, %val) {
		parent::onTrigger(%data, %obj, %trig, %val);
		%vehicle = %obj.getObjectMount();
		%slot = %obj.getMountNode();
		if(isObject(%vehicle)) %fired = RedTurret_Trigger(%vehicle, %slot, %trig, %val, %obj.client);
	}
	function WheeledVehicleData::onTrigger(%data, %vehicle, %trig, %val) {
		parent::onTrigger(%data, %obj, %trig, %val);
		%fired = RedTurret_Trigger(%vehicle, 0, %trig, %val, RedTurret_GetDriverClient(%vehicle));
	}
	function FlyingVehicleData::onTrigger(%data, %vehicle, %trig, %val) {
		parent::onTrigger(%data, %obj, %trig, %val);
		%fired = RedTurret_Trigger(%vehicle, 0, %trig, %val, RedTurret_GetDriverClient(%vehicle));
	}
	
	function WheeledVehicleData::onCollision(%data, %vehicle, %col, %vec, %speed) {
		%vehicle.client = 0;
		parent::onCollision(%data, %vehicle, %col, %vec, %speed);
		RedTurret_VehicleUpdateClient(%vehicle);
	}
	function FlyingVehicleData::onCollision(%data, %vehicle, %col, %vec, %speed) {
		%vehicle.client = 0;
		parent::onCollision(%data, %vehicle, %col, %vec, %speed);
		RedTurret_VehicleUpdateClient(%vehicle);
	}
	
	function ShapeBase::setNodeColor(%obj, %node, %color) {
		parent::setNodeColor(%obj, %node, %color);
		
		if(%obj.getType() & $TypeMasks::PlayerObjectType) {
			MountedTurret_VehicleCreated(%obj);
		}
		
		for(%i=0; %i<%obj.MountedTurret_numTurrets; %i++) {
			%turret = %obj.MountedTurret_turret[%i];
			if(isObject(%turret)) { %turret.setNodeColor("ALL", %color); }
		}
	}
	
	function Armor::onDisabled(%data, %obj) {
		%obj.getDatablock().doDismount(%obj);
		
		parent::onDisabled(%data, %obj);
		
		if(%data.deathExplosionProjectile !$= "") {
			%proj = new Projectile() {
				dataBlock = %data.deathExplosionProjectile;
				initialPosition = %obj.getPosition();
				initialVelocity = "0 0 1";
				client = %obj.lastDamageClient;
				sourceClient = %obj.lastDamageClient;
			};
			MissionCleanup.add(%proj);
			%obj.schedule(10, delete);
		}
	}
	
	function WheeledVehicle::isFirstPerson(%vehicle) {
		return false;
	}
	function FlyingVehicle::isFirstPerson(%vehicle) {
		return false;
	}
	
	function Armor::onMount(%data, %player, %vehicle, %slot) {
		parent::onMount(%data, %player, %vehicle, %slot);
		RedTurret_VehicleUpdateClient(%vehicle);
	}
	function Armor::doDismount(%data, %player, %forced) {
		%vehicle = %player.getObjectMount();
		%slot = %player.getMountNode();
		parent::doDismount(%data, %player, %forced);
		RedTurret_VehicleUpdateClient(%vehicle);
		RedTurret_TriggerOff(%vehicle, %slot);
	}
	function Player::burn(%obj, %time) {
		if(%obj.isTurret) return;
		parent::burn(%obj, %time);
	}
	
	function WeaponImage::onFire(%data, %obj, %slot) {
		parent::onFire(%data, %obj, %slot);
		if(%data.recoilImpulse) {
			%pos = %obj.getMuzzlePoint(%slot);
			%vec = %obj.getMuzzleVector(%slot);
			RedTurret_ApplyRecoilImpulse(%obj, %pos, %vec, %data.recoilImpulse);
		}
	}
	
	function Projectile::onAdd(%proj) {
		parent::onAdd(%proj);
		%proj.client =
			%proj.client ||
			%proj.sourceClient ||
			%proj.sourceObject.client || 
			%proj.sourceObject.RedTurret_Operator;
		%proj.sourceClient = %proj.client;
	}
};
activatePackage(RedBase_MountedTurret);

function MountedTurret_ArmorCreated(%obj) {
	%data = %obj.getDatablock();
	if(%data.animLookLimitUp !$= "")
		%obj.schedule(0, setLookLimits, %data.animLookLimitDown, %data.animLookLimitUp);
}

function RedTurret_Trigger(%vehicle, %slot, %trig, %val, %client) {
	%data = %vehicle.getDatablock();
	for(%i=0; %i<%data.numGuns; %i++) {
		if(%data.gunOperatorSlot[%i] == %slot && %trig == %data.gunTrigger[%i]) {
			%vehicle.setImageTrigger(%data.gunSlot[%i], %val);
			%fired = true;
		}
	}
	for(%i=0; %i<%data.numFixedGuns; %i++) {
		if(%data.gunOperatorSlot[%i] == %slot && %trig == %data.gunTrigger[%i]) {
			RedTurret_TriggerFixedGun(%data, %vehicle, %i, %val, %client);
			%fired = true;
		}
	}
	return %fired;
}
function RedTurret_TriggerOff(%vehicle, %slot) {
	if(!isObject(%vehicle)) return;
	
	%data = %vehicle.getDatablock();
	for(%i=0; %i<%data.numGuns; %i++) {
		if(%data.gunOperatorSlot[%i] == %slot) {
			%vehicle.setImageTrigger(%data.gunSlot[%i], 0);
		}
	}
	for(%i=0; %i<%data.numFixedGuns; %i++) {
		if(%data.gunOperatorSlot[%i] == %slot) {
			RedTurret_TriggerFixedGun(%data, %vehicle, %i, 0, 0);
		}
	}
}

function RedTurret_GetDriverClient(%vehicle) {
	%driver = %vehicle.getMountNodeObject(0);
	if(isObject(%driver) && isObject(%driver.client)) return %driver.client;
	else return 0;
}

function RedTurret_VehicleUpdateClient(%vehicle) {
	if(!isObject(%vehicle)) return;
	%vehicle.RedTurret_Operator = RedTurret_GetDriverClient(%vehicle);
}

function MountedTurret_VehicleCreated(%obj) {
	if(%obj.MountedTurret_Created) return;
	%obj.MountedTurret_Created = 1;
	
	%data = %obj.getDatablock();
	
	for(%i=0; %i<%data.numTurrets; %i++) {
		%tslot = %data.turretSlot[%i];
		%tdata = %data.turretDatablock[%i];
		
		%turret = new AIPlayer() {
			datablock = %tdata;
		};
		if(isObject(%turret)) {
			MissionCleanup.add(%turret);
			%obj.mountObject(%turret, %tslot);
			
			%obj.MountedTurret_turret[%i] = %turret;
			%turret.isTurret = 1;
			%turret.spawnBrick = %obj.spawnBrick;
			%turret.brickGroup = %obj.brickGroup;
		}
	}
	%obj.MountedTurret_numTurrets = %data.numTurrets;
	
	for(%i=0; %i<%data.numGuns; %i++) {
		%gslot = %data.gunSlot[%i];
		%gdata = %data.gunImage[%i];
		
		%obj.mountImage(%gdata, %gslot);
	}
}

function MountedTurret_VehicleDamaged(%obj) {
	if(%obj.getDamageLevel() >= %obj.getDatablock().maxDamage) {
		MountedTurret_VehicleDestroyed(%obj, 0);
	}
}

function MountedTurret_VehicleDestroyed(%obj, %forced) {
	for(%i=0; %i<%obj.MountedTurret_numTurrets; %i++) {
		%turret = %obj.MountedTurret_turret[%i];
		if(isObject(%turret)) {
			if(%forced) {
				%turret.delete();
			} else {
				%turret.kill();
			}
		}
	}
}

function RedTurret_ApplyRecoilImpulse(%obj, %pos, %vec, %mag) {
	while(isObject(%mount = %obj.getObjectMount())) %obj = %mount;
	%obj.applyImpulse(%pos, vectorScale(%vec, -%mag));
}

function RedTurret_TriggerFixedGun(%data, %vehicle, %i, %val, %client) {
	%vehicle.RedTurret_FixedGunClient[%i] = %client;
	%vehicle.RedTurret_FixedGunTrigger[%i] = %val;
	
	if(%val && !%vehicle.RedTurret_FixedGunNotReady[%i])
		RedTurret_FireFixedGun(%data, %vehicle, %i);
}

function RedTurret_GetFixedGunPos(%data, %vehicle, %i) {
	%slot = %data.fixedGunSlot[%i];
	return vectorAdd(
		%vehicle.getSlotTransform(%slot),
		vectorScale(%vehicle.getMuzzleVector(%slot), %data.fixedGunForwardOffset[%i])
	);
}

function RedTurret_FireFixedGun(%data, %vehicle, %i) {
	%vehicle.RedTurret_FixedGunNotReady[%i] = 1;
	
	%slot = %data.fixedGunSlot[%i];
	%pos = RedTurret_GetFixedGunPos(%data, %vehicle, %i);
	%vec = %vehicle.getMuzzleVector(%slot);
	
	%projdata = %data.fixedGunProjectile[%i];
	if(%projdata !$= "") {
		%vel = vectorAdd(
			vectorScale(%vec, %projdata.muzzleVelocity),
			vectorScale(%vehicle.getVelocity(), %projdata.velInheritFactor)
		);
		%proj = new Projectile() {
			datablock = %projdata;
			initialPosition = %pos;
			initialVelocity = %vel;
			sourceObject = %vehicle;
			client = %vehicle.RedTurret_FixedGunClient[%i];
			sourceClient = %vehicle.RedTurret_FixedGunClient[%i];
			sourceSlot = 0;
			originPoint = %pos;
		};
		MissionCleanup.add(%proj);
		%proj.setScale(%vehicle.getScale());
	}
	
	if(%data.fixedGunEmitterImage[%i] !$= "") {
		%vehicle.unmountImage(%slot);
		//%vehicle.mountImage(%data.fixedGunEmitterImage[%i], %slot);
		schedule(33, 0, RedTurret_MountImage, %vehicle, %data.fixedGunEmitterImage[%i], %slot);
		cancel(%vehicle.RedTurret_EmitterSchedule);
		%vehicle.RedTurret_EmitterSchedule = schedule(%data.fixedGunEmitterTimeMs[%i], 0, RedTurret_UnmountImage, %vehicle, %slot);
	}
	
	if(%data.fixedGunRecoilImpulse[%i]) RedTurret_ApplyRecoilImpulse(%vehicle, %pos, %vec, %data.fixedGunRecoilImpulse[%i]);
	
	if(%data.fixedGunFireSound[%i] !$= "") serverPlay3D(%data.fixedGunFireSound[%i], %pos);
	if(%data.fixedGunFireAnimation[%i] !$= "") %vehicle.playThread($RedTurret_AnimThread, %data.fixedGunFireAnimation[%i]);
	
	schedule(%data.fixedGunShotTimeMs[%i], 0, RedTurret_ReadyFixedGun, %data, %vehicle, %i);
	
	if(isFunction(%data, %data.fixedGunFireCallback[%i])) %data.call(%data.fixedGunFireCallback[%i], %vehicle, %i);
}

function RedTurret_MountImage(%obj, %image, %slot) {
	if(!isObject(%obj)) return;
	%obj.mountImage(%image, %slot);
}
function RedTurret_UnmountImage(%obj, %slot) {
	if(!isObject(%obj)) return;
	%obj.unmountImage(%slot);
}

function RedTurret_ReadyFixedGun(%data, %vehicle, %i) {
	if(!isObject(%vehicle)) return;
	%vehicle.RedTurret_FixedGunNotReady[%i] = 0;
	
	%pos = RedTurret_GetFixedGunPos(%data, %vehicle, %i);
	
	if(%data.fixedGunReadySound[%i] !$= "") serverPlay3D(%data.fixedGunReadySound[%i], %pos);
	
	if(isFunction(%data, %data.fixedGunReadyCallback[%i]))
		%data.call(%data.fixedGunReadyCallback[%i], %vehicle, %i);
	
	if(%data.fixedGunIsAutomatic[%i] && %vehicle.RedTurret_FixedGunTrigger[%i])
		RedTurret_FireFixedGun(%data, %vehicle, %i);
}
